Kotlin

Classes and Inheritance

Swift

Classes

                  class Invoice { /*...*/ }
                
                    class Invoice { /*...*/ }

                  
                  class Empty
                
                    class Empty {}

                  

Constructors

                  class Person constructor(firstName: String) { /*...*/ }
                
                    class Person {
    init(firstName: String) {}
    /*...*/
}

                  
                  class Person(firstName: String) { /*...*/ }
                
                    class Person {
    init(firstName: String) { /*...*/ }
}

                  
                  class InitOrderDemo(name: String) {
    val firstProperty = "First property: $name".also(::println)
    
    init {
        println("First initializer block that prints ${name}")
    }
    
    val secondProperty = "Second property: ${name.length}".also(::println)
    
    init {
        println("Second initializer block that prints ${name.length}")
    }
}
                
👏
                    class InitOrderDemo {
    private let name: String
    
    init(name: String) {
        self.name = name
        
        print("First initializer block that prints \(name)")
    }
    
    var firstProperty: String {
        get {
            return "First property: \(self.name)"
        }
    }
    
    var secondProperty: String {
        get {
            return "Second property: \(self.name.count)"
        }
    }
}



                  
                  class Customer(name: String) {
    val customerKey = name.toUpperCase()
}
                
                    class Customer {
    private let name: String
    
    init(name: String) {
        self.name = name
    }
    
    var customerKey: String {
        get { return name.toUpperCase }
    }
}

                  
                  class Person(val firstName: String, val lastName: String, var age: Int) { /*...*/ }
                
                    class Person {
    let firstName, lastName: String
    var age: Int
    
    init(firstName: String, lastName: String, age: Int){
        self.firstName = firstName
        self.lastName = lastName
        self.age = age
    }
    /*...*/
}

                  
                  class Person(
    val firstName: String,
    val lastName: String,
    var age: Int, // trailing comma
) { /*...*/ }
                
                  class Customer public @Inject constructor(name: String) { /*...*/ }
                

Secondary constructors

                  class Person {
    var children: MutableList<Person> = mutableListOf()
    constructor(parent: Person) {
        parent.children.add(this)
    }
}
                
                    class Person {
    var children: [Person] = []
    
    init(parent: Person) {
        parent.children.append(self)
    }
}

                  
                  class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf()
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
                
                    class Person {
    let name: String
    var children: [Person] = []
    
    init(name: String) {
        self.name = name
    }
    
    convenience init(name: String, parent: Person) {
        self.init(name: name)
        parent.children.append(self)
    }
}

                  
                  class Constructors {
    init {
        println("Init block")
    }
​
    constructor(i: Int) {
        println("Constructor")
    }
}
                
                    class Constructors {
    init() {
        print("Constructor in default")
    }
​
    convenience init(i: Int) {
        print("Constructor with \(i)")
    }
}

                  
                  class DontCreateMe private constructor () { /*...*/ }
                
                    class DontCreateMe {
    private init() { }
    /*...*/
}

                  
                  class Customer(val customerName: String = "")
                
                    class Customer {
    let customerName: String
    init(customerName: String = "") {
        self.customerName = customerName
    }
}

                  

Creating instances of classes

                  val invoice = Invoice()
​
val customer = Customer("Joe Smith")
                
                    let invoice = Invoice()
​
let customer = Customer("Joe Smith")

                  

Inheritance

                  class Example // Implicitly inherits from Any
                
Swift classes do not inherit from a universal base class.
                  open class Base //Class is open for inheritance
                
                    class Base //Class is default open for inheritance

                  
                  open class Base(p: Int)
​
class Derived(p: Int) : Base(p)
                
                    class Base {
    init(p: Int) {}
}

class Derived: Base {}

                  
                  class MyView : View {
    constructor(ctx: Context) : super(ctx)
​
    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}
                
                    class MyView: View {
    override init(ctx: Context) {
        super.init(ctx: ctx)
    }
    
    override init(ctx: Context, attrs: AttributeSet) {
        super.init(ctx: ctx, attrs: attrs)
    }
}

                  

Overriding methods

                  open class Shape {
    open fun draw() { /*...*/ }
    fun fill() { /*...*/ }
}
​
class Circle() : Shape() {
    override fun draw() { /*...*/ }
}
                
                    class Shape {
    func draw() { /*...*/ }
    private func fill() { /*...*/ }
}
​
class Circle: Shape {
    override func draw() { /*...*/ }
}

                  
                  open class Rectangle() : Shape() {
    final override fun draw() { /*...*/ }
}
                
                    class Rectangle: Shape {
    final override func draw() { /*...*/ }
}

                  

Overriding properties

                  open class Shape {
    open val vertexCount: Int = 0
}
​
class Rectangle : Shape() {
    override val vertexCount = 4
}
                
                    class Shape {
    var vertexCount: Int = 0
}

class Rectangle: Shape {
    override init() {
        super.init()
        vertexCount = 4
    }
}

                  
                  interface Shape {
    val vertexCount: Int
}
​
class Rectangle(override val vertexCount: Int = 4) : Shape // Always has 4 vertices
​
class Polygon : Shape {
    override var vertexCount: Int = 0  // Can be set to any number later
}
                
                    protocol Shape {
    var vertexCount: Int { get }
}

class Rectangle: Shape {
    let vertexCount: Int = 4
}

class Polygon : Shape {
    var vertexCount: Int = 0  // Can be set to any number later
}

                  

Derived class initialization order

                  open class Base(val name: String) {
​
    init { println("Initializing Base") }
​
    open val size: Int = 
        name.length.also { println("Initializing size in Base: $it") }
}
​
class Derived(
    name: String,
    val lastName: String,
) : Base(name.capitalize().also { println("Argument for Base: $it") }) {
​
    init { println("Initializing Derived") }
​
    override val size: Int =
        (super.size + lastName.length).also { println("Initializing size in Derived: $it") }
}
                
                    class Base {
    let name: String
    init(name: String) {
        self.name = name
        print("Initializing Base")
    }
    
    var size: Int {
        get { return name.count }
    }
}

class Derived: Base {
    let lastName: String
    
    init(name: String, lastName: String) {
        self.lastName = lastName
        print("Initializing Derived")
        
        super.init(name: name.uppercased())
    }
    
    override var size: Int {
        get { return super.size + lastName.count }
    }
}

                  

Calling the superclass implementation

                  open class Rectangle {
    open fun draw() { println("Drawing a rectangle") }
    val borderColor: String get() = "black"
}
​
class FilledRectangle : Rectangle() {
    override fun draw() {
        super.draw()
        println("Filling the rectangle")
    }
​
    val fillColor: String get() = super.borderColor
}
                
                    class Rectangle {
    func draw() { print("Drawing a rectangle") }
    var borderColor: String {
        get { "black" }
    }
}

class FilledRectangle: Rectangle {
    override func draw() {
        super.draw()
        print("Filling the rectangle")
    }
    
    var fillColor: String {
        get { super.borderColor }
    }
}

                  
                  class FilledRectangle: Rectangle() {
    override fun draw() { 
        val filler = Filler()
        filler.drawAndFill()
    }
​
    inner class Filler {
        fun fill() { println("Filling") }
        fun drawAndFill() {
            super@FilledRectangle.draw() // Calls Rectangle's implementation of draw()
            fill()
            println("Drawn a filled rectangle with color ${super@FilledRectangle.borderColor}") // Uses Rectangle's implementation of borderColor's get()
        }
    }
}
                
                    class Rectangle {
    func draw() { print("Rectangle")/* ... */ }
}

protocol Polygon {
    func draw()
}
extension Polygon {
    func draw() { print("Polygon")/* ... */ }
}

class Square: Rectangle, Polygon {
    // The compiler requires draw() to be overridden:
    override func draw() {
        super.draw() // call to Rectangle.draw()
    }
}

                  

Overriding rules

                  open class Rectangle {
    open fun draw() { /* ... */ }
}
​
interface Polygon {
    fun draw() { /* ... */ } // interface members are 'open' by default
}
​
class Square() : Rectangle(), Polygon {
    // The compiler requires draw() to be overridden:
    override fun draw() {
        super<Rectangle>.draw() // call to Rectangle.draw()
        super<Polygon>.draw() // call to Polygon.draw()
    }
}
                
                    class Rectangle {
    func draw() { print("Rectangle")/* ... */ }
}

protocol Polygon {
    func draw()
}
extension Polygon {
    func draw() { print("Polygon")/* ... */ }
}

class Square: Rectangle, Polygon {
    // The compiler requires draw() to be overridden:
    override func draw() {
        super.draw() // call to Rectangle.draw()
    }
}

                  

Abstract classes

                  open class Polygon {
    open fun draw() {}
}
​
abstract class Rectangle : Polygon() {
    abstract override fun draw()
}